package com.fzu.normalservice.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fzu.commonutil.ImResult;
import com.fzu.commonutil.entity.AddressBook;
import com.fzu.commonutil.entity.Company;
import com.fzu.commonutil.entity.UserVO;
import com.fzu.commonutil.mapper.CompanyMapper;
import com.fzu.commonutil.params.DataResult;
import com.fzu.commonutil.params.SelectResult;
import com.fzu.commonutil.util.*;
import com.fzu.commonutil.entity.User;
import com.fzu.commonutil.mapper.UserMapper;
import com.fzu.normalservice.config.WxAppConfig;
import com.fzu.normalservice.param.LoginParam;
import com.fzu.normalservice.param.RegisterParam;
import com.fzu.normalservice.param.WxRegisterParam;
import com.fzu.normalservice.result.ComanyUserResult;
import com.fzu.normalservice.result.LoginResult;
import com.fzu.normalservice.result.WxUserResult;
import com.fzu.normalservice.service.ResourceService;
import com.fzu.normalservice.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fzu.commonutil.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang.StringUtils;
import org.aspectj.apache.bcel.classfile.Code;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zyq
 * @since 2023-03-26
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper userMapper;
    private final CompanyMapper companyMapper;
    private final RedisUtil redisUtil;
    private final ResourceService resourceService;

//    @Override
//    public PageVO selectAll(User user,Integer pageNum,Integer pageSize){
//        Page<User> userPage = new Page<>(pageNum,pageSize);
//        Page<User> page = userMapper.selectAll();
//
//       return users;
//    }

    @Override
    public User selectId(int id){
        User i = userMapper.selectId(id);
        return i;
    }

    @Override
    public String selectAccount(String account){
        String password = userMapper.selectAccount(account);
        return password;
    }

    @Override
    public List<User> selectByRole(Integer role){
        List list = userMapper.selectByRole(role);
        return list;
    }

    @Override
    public String addAccount(User user){
        String account = userMapper.addAccount(user);
        return account;
    }

    @Override
    public String updatePassword(User user){
        String password = userMapper.updatePassword(user);
        return password;
    }

    @Override
    public void deleteByIds(int id){

    }

    @Override
    public LoginResult login(LoginParam param) {
        // 检查密码
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getAccount, param.getAccount());
        wrapper.eq(User::getPassword, param.getPassword());
        User user = super.getOne(wrapper);
        if (user == null) {
            throw new ApiException(ErrorEnum.USERNAME_OR_PASSWORD_ERROR);
        }

        // 生成token
        String token = JwtUtil.getToken(user.getAccount());
        // 保存到redis
        redisUtil.set(token, user, JwtUtil.expireTime());
        // 返回用户信息
        LoginResult result = new LoginResult();
        BeanUtils.copyProperties(user, result);
        result.setToken(token);
        result.setResourceList(resourceService.listByRoleId(user.getRole()));
        return result;
    }

    @Override
    public Integer register(RegisterParam param) {
        String account = param.getAccount();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getAccount, account);
        User user = super.getOne(wrapper);
        if (user != null) {
            throw new ApiException(ErrorEnum.USER_REGISTERED);
        }
        User entity = new User();
        entity.setAccount(account);
        entity.setPassword(param.getPassword());
        entity.setNickName(param.getNickName());
        entity.setCompanyId(param.getCompanyId());
        Integer role = param.getRole();
        if (role == null) {
            role = CodeEnum.CONSUMER.getCode();
        }
        entity.setRole(role);
        super.save(entity);
        return entity.getId();
    }

    @Override
    public PageVO list(User user, Integer pageNum, Integer pageSize) {
        // 构造分页参数
        Page<User> pageRequest = new Page<>(pageNum, pageSize);
        //构造条件构造器
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();


        String account = user.getAccount();
        if (StringUtils.isNotBlank(account)) {
            queryWrapper.eq(User::getAccount, account);
        }
        // 添加姓名查询条件（不为空则添加筛选条件）
        String nickName = user.getNickName();
        if (StringUtils.isNotBlank(nickName)) {
            queryWrapper.eq(User::getNickName, nickName);
        }
        Integer role = user.getRole();
        if (role != null) {
            queryWrapper.eq(User::getRole, role);
        }

        userMapper.selectPage(pageRequest, queryWrapper);
        List<User> records = pageRequest.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            Set<Integer> idList = records.stream().filter(e -> e.getCompanyId() != null).map(User::getCompanyId).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(idList)) {
                List<Company> companyList = companyMapper.selectBatchIds(idList);
                Map<Integer, String> companyMap = companyList.stream().collect(Collectors.toMap(Company::getId, Company::getName));
                for (User record : records) {
                    Integer companyId = record.getCompanyId();
                    record.setCompanyName(companyMap.get(companyId));
                }
            }
        }

        return PageVO.convert(pageRequest);
    }

    @Override
    public void updateUser(User user) {
        // 更新是根据id确定记录的，所以必须对id进行非空判断
        if (user.getId() == null){
            throw new ApiException("ID值不能为空");
        }
        super.updateById(user);
    }

    @Override
    public void deleteUser(Integer id){
        super.removeById(id);
    }

    @Override
    public ImResult<UserVO> token(String userToken) {


        if (StringUtils.isBlank(userToken)) {
            throw new ApiException("未登陆，请登陆后再进行操作！");
        }
        User user = JwtUtil.getUser(userToken);


        if (user == null) {
            throw new ApiException("登录已过期，请重新登陆！");
        }

        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setPassword(null);

        userVO.setAccessToken(userToken);

        return ImResult.success(userVO);
    }

    @Override
    public DataResult userData(DataResult result) {
        List<SelectResult> newUserCountList = userMapper.sevenDayNewUser();
        Map<String, Integer> countMap = new HashMap<>(0);
        if (!CollectionUtils.isEmpty(newUserCountList)) {
            countMap = newUserCountList.stream().collect(Collectors.toMap(SelectResult::getTotalDate, SelectResult::getTotal));
        }
        List<String> days = DateUtils.getDays(7);
        List<Integer> counts = new ArrayList<>(7);
        for (String day : days) {
            Integer c = countMap.get(day);
            if (c == null) {
                c = 0;
            }
            counts.add(c);
        }
        result.setUserData(counts);
        result.setUserLabel(days);
        result.setUserCount(userMapper.selectCount(null));
        return result;
    }

    @Override
    public WxUserResult wxRegister(WxRegisterParam param) {
        final WxMaUserService appService = WxAppConfig.wxMaService.getUserService();
        try {
            // 1.根据code获取sessionKey等信息
            WxMaJscode2SessionResult sessionInfo = appService.getSessionInfo(param.getCode());

            // 2.判断用户是否已注册
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getAccount, sessionInfo.getOpenid());
            if (userMapper.selectOne(wrapper) != null) {
                throw new ApiException(ErrorEnum.USER_REGISTERED);
            }

            // 3.用户信息校验
            if (!appService.checkUserInfo(sessionInfo.getSessionKey(), param.getRawData(), param.getSignature())) {
                throw new ApiException(ErrorEnum.CHECK_ERROR);
            }

            // 4.解密用户信息
            WxMaUserInfo userInfo = appService.getUserInfo(sessionInfo.getSessionKey(), param.getEncryptedData(), param.getIv());

            // 6.用户注册，写入数据库
            User user = new User()
                    .setNickName(userInfo.getNickName())
                    .setAccount(sessionInfo.getOpenid())
                    .setType(CodeEnum.WX_USER.getCode())
                    .setRole(CodeEnum.CONSUMER.getCode());
            userMapper.insert(user);
            // 7. 生成token并返回
            WxUserResult result = new WxUserResult();
            BeanUtils.copyProperties(user, result);
            String token = JwtUtil.getToken(user.getAccount());
            result.setToken(token);
            // 保存到redis
            redisUtil.set(token, user, JwtUtil.expireTime());
            return result;
        } catch (WxErrorException e) {
            log.error("【微信用户注册失败】:{}", e.getMessage());
            throw new ApiException(ErrorEnum.WX_USER_REGISTER_FAIL);
        }
    }

    @Override
    public WxUserResult wxLogin(String code) {
        try {
            WxMaJscode2SessionResult sessionInfo = WxAppConfig.wxMaService.getUserService().getSessionInfo(code);
            // 查询用户
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getAccount, sessionInfo.getOpenid())
                    .eq(User::getType, CodeEnum.WX_USER.getCode());
            User wxUser = userMapper.selectOne(wrapper);
            if (wxUser == null) {
                throw new ApiException(ErrorEnum.USER_NO_EXIST);
            }
            WxUserResult result = new WxUserResult();
            BeanUtils.copyProperties(wxUser, result);
            // 生成token并返回
            String token = JwtUtil.getToken(wxUser.getAccount());
            result.setToken(token);
            // 保存到redis
            redisUtil.set(token, wxUser, JwtUtil.expireTime());
            return result;
        } catch (WxErrorException e) {
            log.error("【微信用户登录失败】:{}", e.getMessage());
            throw new ApiException(ErrorEnum.WX_USER_LOGIN_FAIL);
        }
    }

}
